<template>
  <div class="chat-container">
    <!-- 弹幕层 - 根据弹幕开关状态和消息数量显示 -->
    <div v-if="messages.length === 0 && danmakuEnabled" class="custom-danmaku-layer">
      <div
        v-for="danmu in activeDanmus"
        :key="danmu.id"
        class="custom-danmaku-item"
        :style="{
          top: danmu.top + 'px',
          left: danmu.left + 'px',
          color: danmu.color,
          fontSize: danmu.fontSize + 'px'
        }"
      >
        {{ danmu.text }}
      </div>
    </div>

    <div class="header-actions">
      <el-tooltip content="清空聊天记录" placement="bottom" effect="dark">
        <el-button
          circle
          icon="el-icon-delete"
          class="clear-button"
          :disabled="messages.length === 0"
          @click="clearMessages"
        />
      </el-tooltip>

      <!-- 弹幕控制按钮 - 只在空状态时显示 -->
      <el-tooltip
        v-if="messages.length === 0"
        :content="danmakuEnabled ? '关闭弹幕' : '开启弹幕'"
        placement="bottom"
        effect="dark"
      >
        <el-button
          circle
          :icon="danmakuEnabled ? 'el-icon-video-pause' : 'el-icon-video-play'"
          class="danmaku-toggle-button"
          @click="toggleDanmaku"
        />
      </el-tooltip>

    </div>

    <!-- 消息列表 -->
    <div ref="messagesContainer" class="messages-list">
      <!-- 空状态 -->
      <div v-if="messages.length === 0" class="empty-chat-placeholder">
        <div class="placeholder-content">
          <div class="logo-area">
            <img :src="xmlgLogo" alt="厦门理工Logo" class="placeholder-logo">
          </div>
          <h2 class="placeholder-text">厦门理工等你提问</h2>
        </div>

        <!-- 输入区 - 仅在空状态下显示 -->
        <div class="input-area-wrapper-standalone">
          <div class="main-input-box-standalone">
            <el-input
              v-model="inputMessage"
              class="chat-textarea"
              type="textarea"
              :rows="1"
              :autosize="{ minRows: 1, maxRows: 6 }"
              placeholder="有问题，尽管问... (Shift + Enter 换行)"
              resize="none"
              @keydown.enter.native="handleEnter"
            />
            <el-button
              circle
              icon="el-icon-top"
              type="primary"
              class="send-button-standalone"
              :disabled="!inputMessage || !inputMessage.trim() || isLoading"
              @click="sendMessage"
            />
          </div>
          <div class="shortcut-grid">
            <el-button
              v-for="shortcut in shortcuts"
              :key="shortcut.text"
              round
              class="shortcut-btn"
              @click="handleShortcut(shortcut)"
            >
              <i :class="shortcut.icon" />
              <span>{{ shortcut.text }}</span>
            </el-button>
          </div>
          <div class="footer-disclaimer">
            AI生成的内容，仅供参考
          </div>
        </div>
      </div>

      <div
        v-for="(message, index) in messages"
        :key="`msg-${index}-${message.type}`"
        v-memo="[message.content, message.reasoning, message.showReasoning, message.type]"
        :class="['message-row', message.type]"
      >
        <img
          :src="message.type === 'user' ? userAvatar : xmlgLogo"
          alt="Avatar"
          class="chat-avatar"
        >
        <div class="message-content-wrapper">
          <div :class="[message.type === 'user' ? 'user-message-bubble' : 'ai-message-bubble']">
            <div class="markdown-body" v-html="formatMessage(message.content || '...')" />

            <!-- 推理过程显示区域 -->
            <div v-if="message.type === 'ai' && message.reasoning" class="reasoning-section">
              <div class="reasoning-header">
                <el-button
                  type="text"
                  class="toggle-reasoning"
                  @click="toggleReasoning(message)"
                >
                  <i :class="message.showReasoning ? 'el-icon-arrow-down' : 'el-icon-arrow-right'" />
                  思考过程
                </el-button>
              </div>
              <div v-if="message.showReasoning" class="reasoning-content">
                <div class="reasoning-text" v-html="formatMessage(message.reasoning)" />
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 底部输入区域 (仅在对话开始后显示) -->
    <div v-if="messages.length > 0" class="chat-input-section-fixed">
      <div class="input-area-wrapper">
        <div class="main-input-box-standalone">
          <el-input
            v-model="inputMessage"
            class="chat-textarea"
            type="textarea"
            :rows="1"
            :autosize="{ minRows: 1, maxRows: 6 }"
            placeholder="有问题，尽管问... (Shift + Enter 换行)"
            resize="none"
            @keydown.enter.native="handleEnter"
          />
          <el-button
            circle
            icon="el-icon-top"
            type="primary"
            class="send-button-standalone"
            :disabled="!inputMessage || !inputMessage.trim() || isLoading"
            @click="sendMessage"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import axios from 'axios'
import MarkdownIt from 'markdown-it'
import { mapGetters } from 'vuex'
import XmlgLogo from '@/assets/logo/xmlg_logo.png'
import { startDanmaku, stopDanmaku, destroyDanmaku } from '@/utils/danmaku'


const md = new MarkdownIt({
  html: true,
  linkify: true,
  typographer: true
})

export default {
  name: 'ChatRoom',
  components: {},
  data() {
    return {
      xmlgLogo: XmlgLogo,
      messages: [],
      inputMessage: '',
      isLoading: false,
      activeDanmus: [],
      danmakuEnabled: true, // 弹幕开关状态
      shortcuts: [
        { text: '代码改写', icon: 'el-icon-s-platform', prompt: '请帮我重构和优化以下代码，提高其可读性、性能和健壮性：' },
        { text: '代码解释', icon: 'el-icon-s-comment', prompt: '请逐行解释以下代码的功能和逻辑：' },
        { text: '代码生成', icon: 'el-icon-s-opportunity', prompt: '请根据以下需求，生成一段功能完整的代码：' },
        { text: '内容分类', icon: 'el-icon-link', prompt: '请分析以下文本，并将其归类到最合适的类别中：' },
        { text: '结构化输出', icon: 'el-icon-s-order', prompt: '请将以下内容以JSON格式进行结构化输出：' },
        { text: '角色扮演', icon: 'el-icon-user-solid', prompt: '现在你将扮演一个[请填写角色], 与我进行对话。你需要完全沉浸在角色中，以该角色的口吻、性格和知识背景与我交流。' },
        { text: '情景续写', icon: 'el-icon-camera-solid', prompt: '我将提供一个情景的开头，请你以丰富的想象力和细腻的文笔，继续进行场景续写，营造出引人入胜的氛围。开头是：' },
        { text: '散文写作', icon: 'el-icon-s-management', prompt: '请根据以下关键词写一篇优美的散文：' },
        { text: '诗歌创作', icon: 'el-icon-edit', prompt: '请根据以下主题或意象创作一首诗歌：' },
        { text: '文案大纲', icon: 'el-icon-s-grid', prompt: '请为以下主题生成一份详细的文案大纲：' },
        { text: '宣传标语', icon: 'el-icon-s-flag', prompt: '请为以下产品或活动生成几条有创意、吸引人的宣传标语：' },
        { text: '提示词生成', icon: 'el-icon-s-data', prompt: '我希望模型能够[请填写你的目标]，请帮我生成一些高质量的、能够引导模型产出优秀结果的提示词(Prompt)。' },
        { text: '中英翻译', icon: 'el-icon-s-cooperation', prompt: '请将以下内容翻译成[中文/英文]，要求翻译准确、流畅、符合目标语言的表达习惯：' }
      ],
      typingQueue: [],
      isTyping: false,
      typingInterval: 50, // 增加间隔，减少更新频率
      batchSize: 10, // 增加批处理大小
      currentReader: null,
      scrollTimer: null,
      renderTimer: null, // 新增：渲染防抖定时器
      lastScrollTime: 0 // 新增：滚动节流
    }
  },

  computed: {
    ...mapGetters([
      'avatar'
    ]),
    userAvatar() {
      return 'https://q8.itc.cn/q_70/images03/20250114/d9d8d1106f454c2b83ea395927bfc020.jpeg?imageView2/1/w/80/h/80'
    },
    isDanmakuEnabled() {
      return this.danmakuEnabled
    }
  },

  mounted() {
    // 启动弹幕（根据开关状态）
    this.startDanmakuIfNeeded()
  },

  beforeDestroy() {
    // 清理fetch reader连接
    if (this.currentReader) {
      this.currentReader.cancel()
      this.currentReader = null
    }
    // 清理定时器
    if (this.scrollTimer) {
      clearTimeout(this.scrollTimer)
    }
    if (this.renderTimer) {
      clearTimeout(this.renderTimer)
    }
    // 清理缓存
    if (this._markdownCache) {
      this._markdownCache.clear()
    }
    // 清理打字队列
    this.clearTypingQueue()
    // 销毁弹幕管理器
    destroyDanmaku();
  },

  methods: {
    handleShortcut(shortcut) {
      if (this.isLoading) return
      const currentInput = this.inputMessage.trim()
      let prompt = shortcut.prompt

      if (currentInput) {
        // 如果输入框有内容，则追加到预设提示词后面
        prompt += `\n\n---\n${currentInput}`
      }

      this.inputMessage = prompt
      this.sendMessage()
    },

    handleEnter(event) {
      if (event.shiftKey) {
        // Shift+Enter 换行
        return
      }
      // 普通 Enter 发送消息
      event.preventDefault()
      this.sendMessage()
    },

    async sendMessage() {
      if (!this.inputMessage.trim() || this.isLoading) return;

      const userMessage = this.inputMessage.trim();
      this.inputMessage = '';
      // 移除这里的 this.isLoading = true; 让它在实际开始AI请求时再设置

      // 添加用户消息（弹幕会自动停止）
      this.messages.push({
        type: 'user',
        content: userMessage,
        time: this.getCurrentTime()
      });
      this.$nextTick(() => { this.scrollToBottom(); });

      // 调用AI接口
      this.sendMessageWithReasoning(userMessage);
    },

    async sendMessageWithReasoning(userMessage) {
      // 清理之前的fetch reader连接
      if (this.currentReader) {
        this.currentReader.cancel()
        this.currentReader = null
      }

      // 在这里设置 isLoading = true，确保在实际开始请求时才禁用按钮
      this.isLoading = true;

      const aiMessageIndex = this.messages.length
      this.messages.push({
        type: 'ai',
        content: '',
        reasoning: '',
        showReasoning: false,
        time: this.getCurrentTime()
      })

      // 确保消息对象已经被Vue响应式系统处理
      this.$set(this.messages[aiMessageIndex], 'reasoning', '')
      this.$set(this.messages[aiMessageIndex], 'showReasoning', false)
      this.$nextTick(() => { this.scrollToBottom() })

      try {
        // 使用fetch API替代EventSource以支持自定义请求头
        const token = localStorage.getItem('token')
        const url = `/api/ai/generateStreamWithReasoning?message=${encodeURIComponent(userMessage)}`

        // 设置超时处理
        const controller = new AbortController()
        const timeout = setTimeout(() => {
          console.error('SSE连接超时')
          controller.abort()
          if (this.messages[aiMessageIndex]) {
            this.messages[aiMessageIndex].content = '连接超时，请重试。'
          }
          this.isLoading = false
          this.clearTypingQueue()
        }, 30000) // 30秒超时

        const response = await fetch(url, {
          method: 'GET',
          headers: {
            'Accept': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'token': token || ''
          },
          signal: controller.signal
        })

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`)
        }

        console.log('SSE连接已建立')
        clearTimeout(timeout)

        const reader = response.body.getReader()
        const decoder = new TextDecoder()
        let buffer = ''

        // 清理之前的连接（如果存在）
        if (this.currentReader) {
          try {
            await this.currentReader.cancel()
            console.log('清理了之前的SSE连接')
          } catch (e) {
            console.warn('清理之前连接时出错:', e)
          }
        }

        // 保存新的reader引用以便清理
        this.currentReader = reader

        while (true) {
          const { done, value } = await reader.read()

          if (done) {
            console.log('SSE流正常结束')
            this.isLoading = false
            // 移除打字效果，直接完成
            this.finishTyping(aiMessageIndex)
            this.currentReader = null
            break
          }

          buffer += decoder.decode(value, { stream: true })
          const lines = buffer.split('\n')
          buffer = lines.pop() || '' // 保留最后一行（可能不完整）

          let currentEvent = ''

          for (const line of lines) {
            if (line.trim() === '') continue

            if (line.startsWith('event:')) {
              // 兼容 'event:' 和 'event: ' 两种格式
              currentEvent = line.slice(6).trim() // 移除 'event:' 前缀并去除空格
              console.log('解析到事件名称:', currentEvent)
            } else if (line.startsWith('data:')) {
              // 兼容 'data:' 和 'data: ' 两种格式
              const data = line.slice(5).trim() // 移除 'data:' 前缀并去除空格

              if (data === '[DONE]') {
                console.log('接收到[DONE]标记，结束SSE流')
                this.isLoading = false
                this.finishTyping(aiMessageIndex)
                if (this.currentReader) {
                  try {
                    await this.currentReader.cancel()
                    this.currentReader = null
                    console.log('SSE连接已清理')
                  } catch (e) {
                    console.warn('清理连接时出错:', e)
                  }
                }
                return
              }

              try {
                const parsedData = JSON.parse(data)

                if (currentEvent === 'content' && parsedData.type === 'content') {
                  // 优化：使用批量更新而不是逐字符打字
                  if (this.messages[aiMessageIndex] && parsedData.content) {
                    this.updateContentBatch(aiMessageIndex, parsedData.content)
                  }
                } else if (currentEvent === 'reasoning' && parsedData.type === 'reasoning') {
                  if (this.messages[aiMessageIndex] && parsedData.content) {
                    if (typeof this.messages[aiMessageIndex].reasoning === 'undefined') {
                      this.$set(this.messages[aiMessageIndex], 'reasoning', '')
                    }
                    this.$set(this.messages[aiMessageIndex], 'showReasoning', true)
                    this.updateReasoningBatch(aiMessageIndex, parsedData.content)
                  }
                } else if (currentEvent === 'complete' && parsedData.type === 'complete') {
                  // 完成处理 - 处理最终的完整内容
                  console.log('接收到complete事件', parsedData)

                  // 如果有最终内容，确保显示完整内容
                  if (parsedData.finalContent && this.messages[aiMessageIndex]) {
                    const currentContent = this.messages[aiMessageIndex].content || ''
                    if (parsedData.finalContent !== currentContent) {
                      // 如果最终内容与当前内容不同，更新为最终内容
                      this.messages[aiMessageIndex].content = parsedData.finalContent
                      console.log('更新最终内容:', parsedData.finalContent)
                    }
                  }

                  // 如果有推理内容，确保显示完整推理
                  if (parsedData.reasoningContent && this.messages[aiMessageIndex]) {
                    if (typeof this.messages[aiMessageIndex].reasoning === 'undefined') {
                      this.$set(this.messages[aiMessageIndex], 'reasoning', '')
                    }
                    if (parsedData.reasoningContent !== this.messages[aiMessageIndex].reasoning) {
                      this.messages[aiMessageIndex].reasoning = parsedData.reasoningContent
                      console.log('更新最终推理内容:', parsedData.reasoningContent)
                    }
                  }

                  this.isLoading = false
                  this.finishTyping(aiMessageIndex)

                  // 清理连接
                  if (this.currentReader) {
                    try {
                      await this.currentReader.cancel()
                      this.currentReader = null
                      console.log('SSE连接已清理')
                    } catch (e) {
                      console.warn('清理连接时出错:', e)
                    }
                  }
                  return
                } else {
                  // 未匹配的事件类型，记录日志
                  console.warn('未处理的SSE事件:', '事件名称:', currentEvent, '数据类型:', parsedData.type, '完整数据:', parsedData)
                }
              } catch (error) {
                console.error('解析SSE数据时出错:', error, 'Raw data:', data)
              }
            }
          }
        }
      } catch (error) {
        console.error('发送消息时出错:', error)
        if (this.messages[aiMessageIndex]) {
          this.messages[aiMessageIndex].content = '抱歉，处理回复时发生错误。'
        }
        this.isLoading = false
        this.clearTypingQueue()

        // 清理SSE连接
        if (this.currentReader) {
          try {
            await this.currentReader.cancel()
            this.currentReader = null
            console.log('SSE连接已清理')
          } catch (cleanupError) {
            console.error('清理SSE连接时出错:', cleanupError)
          }
        }
      }
    },

    async sendMessageOld() {
      if (!this.inputMessage.trim() || this.isLoading) return

      const userMessage = this.inputMessage.trim()
      this.inputMessage = ''

      this.messages.push({
        type: 'user',
        content: userMessage,
        time: this.getCurrentTime()
      })
      this.$nextTick(() => { this.scrollToBottom() })

      // No initial isLoading = true for AI thinking message, start typing directly
      // this.isLoading = true;

      const aiMessageIndex = this.messages.length
      this.messages.push({
        type: 'ai',
        content: '', // Start with empty content for typing effect
        time: this.getCurrentTime()
      })
      this.$nextTick(() => { this.scrollToBottom() })

      let buffer = ''
      let receivedTextForSlicing = '' // To keep track of the full response text for slicing

      try {
        await axios({
          method: 'GET',
          url: `/api/ai/generateStream?message=${encodeURIComponent(userMessage)}`,
          headers: { 'token': localStorage.getItem('token') },
          responseType: 'text',
          onDownloadProgress: (progressEvent) => {
            const currentResponse = progressEvent.currentTarget.response || ''
            const newResponseChunk = currentResponse.slice(receivedTextForSlicing.length)
            receivedTextForSlicing = currentResponse

            if (newResponseChunk) {
              buffer += newResponseChunk
              const lines = buffer.split('\n')
              const lastLine = lines.pop() || ''
              lines.forEach(line => {
                if (line.trim()) {
                  try {
                    const jsonData = JSON.parse(line.trim())
                    const textContent = this.extractTextFromJson(jsonData)
                    if (textContent) {
                      this.enqueueTextForTyping(textContent, aiMessageIndex)
                    }
                  } catch (error) {
                    // console.warn('Stream JSON parsing error, skipping line:', error.message, line.trim());
                  }
                }
              })
              buffer = lastLine
            }
          }
        })

        // Axios request finished successfully
        // Process any remaining data in the buffer
        if (buffer.trim()) {
          try {
            const jsonData = JSON.parse(buffer.trim())
            const textContent = this.extractTextFromJson(jsonData)
            if (textContent) {
              this.enqueueTextForTyping(textContent, aiMessageIndex)
            }
          } catch (error) {
            // console.warn('Final buffer JSON parsing error:', error.message, buffer.trim());
            if (buffer.trim()) { // Fallback for non-JSON text
              this.enqueueTextForTyping(buffer.trim(), aiMessageIndex)
            }
          }
        }
        // Signal that all data has been enqueued and the queue should now finalize.
        this.processTypingQueue(aiMessageIndex, true) // true indicates it's the final processing call
      } catch (error) { // Catches errors from axios request or initial setup
        console.error('发送消息或处理响应时出错:', error)
        if (this.messages[aiMessageIndex]) {
          this.messages[aiMessageIndex].content = '抱歉，处理回复时发生错误。'
        }
        this.isLoading = false // Set loading to false on error
        this.clearTypingQueue()
        console.log('isLoading设置为false (axios error or setup error)')
      }
    },

    extractTextFromJson(jsonData) {
      let textContent = ''
      if (Array.isArray(jsonData)) {
        textContent = jsonData.map(item => {
          if (typeof item === 'object' && item !== null) {
            return item.result?.output?.text || item.text || ''
          } else if (typeof item === 'string') {
            return item
          }
          return ''
        }).filter(Boolean).join('')
      } else if (typeof jsonData === 'object' && jsonData !== null) {
        textContent = jsonData.result?.output?.text ||
          jsonData.output?.text ||
          jsonData.text ||
          jsonData.content ||
          jsonData.message ||
          ''
        if (!textContent && jsonData.data && Array.isArray(jsonData.data)) {
          textContent = jsonData.data.map(item => {
            if (typeof item === 'object' && item !== null) {
              return item.result?.output?.text || item.text || ''
            }
            return ''
          }).filter(Boolean).join('')
        }
      } else if (typeof jsonData === 'string') {
        textContent = jsonData
      }
      return textContent
    },

    enqueueTextForTyping(text, messageIndex, type = 'content') {
      if (!text) return

      console.log('入队文本:', '类型:', type, '消息索引:', messageIndex, '文本长度:', text.length, '文本内容:', text.substring(0, 50) + (text.length > 50 ? '...' : ''))

      this.typingQueue.push({
        text: text,
        messageIndex: messageIndex,
        type: type
      })

      console.log('当前队列长度:', this.typingQueue.length, '是否正在打字:', this.isTyping)

      if (!this.isTyping) {
        this.isLoading = true // Set loading true when typing starts
        this.processTypingQueue()
      }
    },

    // 优化：批量更新内容方法，减少DOM操作
    updateContentBatch(messageIndex, newContent) {
      if (!this.messages[messageIndex]) return

      const message = this.messages[messageIndex]
      if (message.content !== newContent) {
        // 直接更新，避免触发过多响应式更新
        this.$set(this.messages, messageIndex, {
          ...message,
          content: newContent
        })

        // 节流滚动更新
        this.throttleScroll()
      }
    },

    // 优化：批量更新推理内容方法，减少DOM操作
    updateReasoningBatch(messageIndex, newReasoning) {
      if (!this.messages[messageIndex]) return

      const message = this.messages[messageIndex]
      if (message.reasoning !== newReasoning) {
        // 直接更新，避免触发过多响应式更新
        this.$set(this.messages, messageIndex, {
          ...message,
          reasoning: newReasoning,
          showReasoning: true
        })

        // 节流滚动更新
        this.throttleScroll()
      }
    },

    // 新增：节流滚动方法
    throttleScroll() {
      const now = Date.now()
      if (now - this.lastScrollTime > 100) { // 100ms节流
        this.lastScrollTime = now
        this.$nextTick(() => {
          requestAnimationFrame(() => {
            this.scrollToBottom()
          })
        })
      }
    },

    // 新增：完成打字效果
    finishTyping(messageIndex) {
      this.clearTypingQueue()
      this.isLoading = false
      this.isTyping = false
    },

    // 优化后的打字效果，大幅减少DOM更新频率
    processTypingQueue(currentMessageIndexForCompletion = null, isFinalCallAfterStream = false) {
      if (this.typingQueue.length === 0) {
        this.isTyping = false
        if (isFinalCallAfterStream) {
          this.isLoading = false
        }
        return
      }

      this.isTyping = true
      const { text, messageIndex, type } = this.typingQueue.shift()

      // 如果文本很短，直接一次性显示
      if (text.length < 100) {
        if (this.messages[messageIndex]) {
          if (type === 'reasoning') {
            const message = this.messages[messageIndex]
            this.$set(this.messages, messageIndex, {
              ...message,
              reasoning: (message.reasoning || '') + text,
              showReasoning: true
            })
          } else {
            const message = this.messages[messageIndex]
            this.$set(this.messages, messageIndex, {
              ...message,
              content: (message.content || '') + text
            })
          }
          this.throttleScroll()
        }
        // 处理下一条
        setTimeout(() => {
          this.processTypingQueue(currentMessageIndexForCompletion, isFinalCallAfterStream)
        }, 0)
        return
      }

      // 对于长文本，分批处理
      let charIndex = 0
      const processNextBatch = () => {
        if (charIndex < text.length && this.messages[messageIndex]) {
          // 大幅增加批处理大小，减少更新次数
          const endIndex = Math.min(charIndex + this.batchSize * 5, text.length)
          const batch = text.slice(charIndex, endIndex)
          const message = this.messages[messageIndex]

          if (type === 'reasoning') {
            this.$set(this.messages, messageIndex, {
              ...message,
              reasoning: (message.reasoning || '') + batch,
              showReasoning: true
            })
          } else {
            this.$set(this.messages, messageIndex, {
              ...message,
              content: (message.content || '') + batch
            })
          }

          charIndex = endIndex
          // 只在每批次结束时节流滚动
          this.throttleScroll()

          // 使用requestAnimationFrame调度下一批，减少UI阻塞
          requestAnimationFrame(() => {
            setTimeout(processNextBatch, this.typingInterval)
          })
        } else {
          // 处理下一条消息
          setTimeout(() => {
            this.processTypingQueue(currentMessageIndexForCompletion, isFinalCallAfterStream)
          }, 0)
        }
      }

      processNextBatch()
    },

    clearTypingQueue() {
      this.typingQueue = []
      this.isTyping = false
      this.isLoading = false
    },

    toggleDanmaku() {
      this.danmakuEnabled = !this.danmakuEnabled

      if (this.danmakuEnabled) {
        // 开启弹幕
        if (this.messages.length === 0) {
          this.startDanmakuIfNeeded()
        }
        this.$message.success('弹幕已开启')
      } else {
        // 关闭弹幕
        stopDanmaku()
        this.activeDanmus = []
        this.$message.success('弹幕已关闭')
      }
    },

    toggleReasoning(message) {
      this.$set(message, 'showReasoning', !message.showReasoning)
    },

    clearMessages() {
      if (this.messages.length === 0) return

      this.$confirm('确定要清空所有聊天记录吗？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        this.messages = []
        this.$message.success('聊天记录已清空')

        // 清除对话后重新启动弹幕（如果弹幕开关是开启状态）
        if (this.danmakuEnabled) {
          this.startDanmakuIfNeeded()
        }
      }).catch(() => {})
    },

    getCurrentTime() {
      const now = new Date()
      return now.toLocaleTimeString('zh-CN', {
        hour12: false,
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit'
      })
    },

    formatMessage(content) {
      if (!content) return ''

      // 添加缓存机制，避免重复解析相同内容
      if (!this._markdownCache) {
        this._markdownCache = new Map()
      }

      if (this._markdownCache.has(content)) {
        return this._markdownCache.get(content)
      }

      let result
      // 使用 markdown-it 渲染 Markdown 格式
      try {
        result = md.render(content)
      } catch (error) {
        console.warn('Markdown渲染失败，使用原始内容:', error)
        // 如果Markdown渲染失败，回退到简单的格式化
        result = content
          .replace(/\n/g, '<br>')
          .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
          .replace(/\*(.*?)\*/g, '<em>$1</em>')
      }

      // 缓存结果，但限制缓存大小
      if (this._markdownCache.size > 100) {
        const firstKey = this._markdownCache.keys().next().value
        this._markdownCache.delete(firstKey)
      }
      this._markdownCache.set(content, result)

      return result
    },

    // 优化滚动方法
    scrollToBottom() {
      const container = this.$refs.messagesContainer
      if (!container) return

      // 检查是否需要滚动（如果用户已经向上滚动查看历史消息，则不自动滚动）
      const isNearBottom = container.scrollHeight - container.scrollTop - container.clientHeight < 100
      if (!isNearBottom && this.messages.length > 1) return

      // 使用transform代替scrollTop，性能更好
      const scrollHeight = container.scrollHeight
      const clientHeight = container.clientHeight
      const maxScrollTop = scrollHeight - clientHeight

      if (maxScrollTop > 0) {
        // 使用passive模式滚动，减少主线程阻塞
        requestAnimationFrame(() => {
          container.scrollTo({
            top: maxScrollTop,
            behavior: 'auto' // 使用'auto'而不是'smooth'以提高性能
          })
        })
      }
    },

    // 启动弹幕的辅助方法
    startDanmakuIfNeeded() {
      if (this.danmakuEnabled && this.messages.length === 0) {
        startDanmaku(
          (danmus) => {
            this.activeDanmus = danmus
          },
          () => this.messages.length
        )
      }
    }


  }
}
</script>

<style scoped lang="scss">
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@400;500;700&display=swap');

$theme-color: #AE0923; // 厦门理工红
$user-msg-bg: #fdebee;
$user-msg-text: $theme-color;

$bg-color: #ffffff;
$text-primary: #1f2329;
$text-secondary: #646a73;
$border-color: #e5e6e8;
$ai-msg-bg: #f2f3f5; /* 恢复AI气泡色 */
$shortcut-btn-bg: #f7f7fa;
$input-box-bg: #ffffff;

.chat-container {
  display: flex;
  flex-direction: column;
  height: calc(100vh - 50px);
  background-color: $bg-color;
  font-family: 'Noto Sans SC', sans-serif;
  position: relative;
}



.header-actions {
  position: absolute;
  top: 24px;
  left: 24px; /* 移动到左边 */
  right: auto;   /* 重置right */
  z-index: 10;
  display: flex;
  gap: 10px;
}

.messages-list {
  flex: 1;
  overflow-y: auto;
  padding: 24px;
  padding-bottom: 150px; /* 为底部固定输入框留出空间 */
  box-sizing: border-box;
}

.empty-chat-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 100%;
  box-sizing: border-box;
}

.placeholder-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin-bottom: 40px;
}

.logo-area { margin-bottom: 24px; }
.placeholder-logo { width: 60px; height: 60px; }
.placeholder-text { font-size: 28px; font-weight: 700; color: #3d4757; margin: 0; }

/* 独立输入区 (空状态时) */
.input-area-wrapper-standalone {
  width: 100%;
  max-width: 980px;
  margin: 0 auto;
}

.message-row {
  display: flex;
  margin-bottom: 16px; /* 统一设置消息行间距 */
  align-items: flex-start;
  gap: 8px; /* 减少头像和消息的间距 */
  &.user { flex-direction: row-reverse; }

  /* 最后一个消息不需要底部间距 */
  &:last-child {
    margin-bottom: 0;
  }
}

.chat-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  flex-shrink: 0;
}

/* 为消息气泡添加更小的间距 */
.message-content-wrapper {
  max-width: 70%;
  margin-bottom: 0; /* 移除此处的间距，统一由 .message-row 控制 */
}

.ai-message-bubble, .user-message-bubble {
  padding: 12px 16px;
  border-radius: 12px;
  word-break: break-word;
  line-height: 1.7;
  box-shadow: 0 1px 4px rgba(0,0,0,0.04);

  ::v-deep .markdown-body {
    // 1. 统一的垂直间距，避免边距叠加
    > * + * {
      margin-top: 12px;
    }

    // 2. 基础元素重置
    p, blockquote, h1, h2, h3, h4, h5, h6 {
      margin: 0;
    }

    // 3. 列表样式 (关键：恢复内边距以显示项目符号)
    ul, ol {
      margin: 0;
      padding-left: 24px;
    }

    // 4. 通用代码块样式
    pre {
      margin: 0;
      white-space: pre-wrap;
      word-wrap: break-word;
      padding: 16px;
      border-radius: 8px;
      line-height: 1.5;
      font-size: 14px;
      // 移除 pre 标签内的 code 标签的背景和内边距
      code {
        background: none;
        padding: 0;
      }
    }

    // 5. 通用行内代码样式
    code:not(pre > code) {
      padding: 3px 6px;
      border-radius: 4px;
      font-size: 0.9em;
    }

    // 6. 分割线样式
    hr {
      margin: 0; // 间距由 * + * 控制
      border: 0;
      height: 1px;
    }
  }
}

.ai-message-bubble {
  background-color: $ai-msg-bg;
  color: $text-primary;
  border-top-left-radius: 0;

  /* AI 气泡内的 Markdown 元素定制 */
  ::v-deep .markdown-body {
    pre { background-color: #eef0f2; }
    code:not(pre > code) { background-color: #eef0f2; }
    hr { background-color: #dde0e3; }
  }
}

.user-message-bubble {
  background-color: $user-msg-bg;
  color: $user-msg-text;
  border-top-right-radius: 0;

  /* 用户气泡内的 Markdown 元素定制 */
  ::v-deep .markdown-body {
    pre { background-color: rgba($theme-color, 0.08); }
    code:not(pre > code) { background-color: rgba($theme-color, 0.08); }
    hr { background-color: rgba($theme-color, 0.2); }
  }
}

/* 底部固定输入区 (对话时) */
.chat-input-section-fixed {
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  padding: 16px 24px 24px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, $bg-color 40%, $bg-color 100%);
  .input-area-wrapper {
    max-width: 980px;
    margin: 0 auto;
  }
}

/* 统一的新输入框样式 */
.main-input-box-standalone {
  position: relative;
  display: flex;
  align-items: center;
  background-color: $input-box-bg;
  border: 1px solid $border-color;
  border-radius: 24px;
  padding: 8px;
  padding-left: 24px;
  padding-right: 64px; /* 为按钮留出空间 */
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.07);
  transition: all 0.2s ease-in-out;
  &:focus-within {
    border-color: rgba($theme-color, 0.5);
    box-shadow: 0 8px_32px rgba(174, 9, 35, 0.15);
  }
}

::v-deep .chat-textarea .el-textarea__inner {
  background-color: transparent;
  border: none;
  box-shadow: none;
  padding: 8px 0;
  line-height: 1.8;
  font-size: 16px;
  color: $text-primary;
  resize: none !important;
  &::placeholder {
    color: #a4a9b2;
  }
}

.send-button-standalone {
  position: absolute;
  right: 8px;
  top: 50%;
  transform: translateY(-50%);
  width: 44px;
  height: 44px;
  background-color: lighten($theme-color, 15%);
  border: none;
  box-shadow: 0 2px 8px rgba(174, 9, 35, 0.15);
  transition: all 0.2s ease-in-out;

  i {
    font-size: 20px;
    font-weight: bold;
  }

  &:hover {
    background-color: lighten($theme-color, 5%);
    transform: translateY(-50%) scale(1.02);
    box-shadow: 0 4px 12px rgba(174, 9, 35, 0.2);
  }

  &:disabled {
    background-color: lighten($theme-color, 35%);
    box-shadow: none;
    transform: translateY(-50%);
    cursor: not-allowed;
    opacity: 0.6;
  }
}

/* 快捷按钮 */
.shortcut-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 24px;
  justify-content: center;
}

.shortcut-btn {
  background-color: $shortcut-btn-bg;
  border: 1px solid $shortcut-btn-bg;
  color: $text-primary;
  padding: 8px 16px;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.2s ease;
  i { margin-right: 8px; font-size: 16px; }
  &:hover {
    border-color: #d8dbe0;
    background-color: #fff;
  }
}

.footer-disclaimer {
  text-align: center;
  font-size: 14px;
  color: $text-secondary;
  margin-top: 24px;
}

/* 弹幕层样式 */
.custom-danmaku-layer {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  z-index: 1;
  overflow: hidden;
}

.custom-danmaku-item {
  position: absolute;
  white-space: nowrap;
  font-weight: 500;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);
  animation: danmaku-move linear infinite;
  pointer-events: none;
}

@keyframes danmaku-move {
  from {
    transform: translateX(100vw);
  }
  to {
    transform: translateX(-100%);
  }
}

/* 清理不再使用的旧样式 */
.chat-input-section-unified, .main-input-box-unified, .input-actions-bar, .action-btn, .shortcut-dropdown, .footer-disclaimer-standalone, .chat-input-section, .input-area-wrapper-empty, .main-input-box {
  display: none;
}

/* 推理过程样式 */
.reasoning-section {
  margin-top: 12px;
  border: 1px solid #e5e6e8;
  border-radius: 8px;
  overflow: hidden;
  background-color: #fafafa;
}

.reasoning-header {
  padding: 8px 12px;
  background-color: #f5f5f5;
  border-bottom: 1px solid #e5e6e8;
  cursor: pointer;

  .toggle-reasoning {
    padding: 0;
    font-size: 14px;
    color: $text-secondary;

    &:hover {
      color: $theme-color;
    }

    i {
      margin-right: 6px;
    }
  }
}

.reasoning-content {
  padding: 12px;
  background-color: #fafafa;
}

.reasoning-text {
  font-size: 14px;
  line-height: 1.6;
  color: $text-secondary;
  border-left: 3px solid $theme-color;
  padding-left: 12px;

  ::v-deep {
    p {
      margin: 0 0 8px 0;

      &:last-child {
        margin-bottom: 0;
      }
    }

    code {
      background-color: rgba($theme-color, 0.1);
      color: $theme-color;
      padding: 2px 4px;
      border-radius: 3px;
      font-size: 13px;
    }

    pre {
      background-color: #f8f8f8;
      border: 1px solid #e5e6e8;
      border-radius: 4px;
      padding: 8px;
      margin: 8px 0;
      overflow-x: auto;

      code {
        background: none;
        color: inherit;
        padding: 0;
      }
    }
  }
}

.clear-button {
  background-color: #f2f3f5;
  border: 1px solid #f2f3f5;
  color: #4e5969;
  font-size: 18px; /* 调整图标大小 */
  transition: all 0.2s ease;
  &:hover {
    color: $theme-color;
    background-color: lighten($theme-color, 35%);
    border-color: lighten($theme-color, 30%);
  }
}

.danmaku-toggle-button {
  background-color: #f2f3f5;
  border: 1px solid #e5e6e8;
  color: #4e5969;
  font-size: 18px;
  transition: all 0.2s ease;
}

.danmaku-toggle-button:hover {
  background-color: #e8f4fd;
  border-color: #409eff;
  color: #409eff;
}

.user-message-text {
  white-space: pre-wrap; /* 保持换行和空格 */
  word-wrap: break-word; /* 长单词换行 */
  font-family: inherit;
  margin: 0;
  padding: 0;
  background: none;
  border: none;
}

.user-message-bubble .markdown-body {
  white-space: pre-wrap;
  word-wrap: break-word;
}

.message-content {
  width: 100%;
  overflow-wrap: break-word;
}
</style>
